package com.googlecode.flair
{
	import flash.display.DisplayObject;
	import flash.events.MouseEvent;
	import flash.utils.Dictionary;
	import flash.utils.getDefinitionByName;
	import flash.utils.getQualifiedClassName;
	
	import mx.collections.ArrayCollection;
	import mx.containers.Box;
	import mx.containers.Panel;
	import mx.core.Container;
	import mx.core.UIComponent;
	import mx.styles.CSSStyleDeclaration;
	import mx.utils.ArrayUtil;

	[Bindable]
	public class FlairComponent implements IFlairComponent
	{
		
		public var component : Object;
		public var componentId : String;
		public var icon : Class;
		public var parentComponent : IFlairComponent = null;
		public var components : ArrayCollection = new ArrayCollection();
		
		public var editedProperties : Dictionary = new Dictionary();
		public var editedStyles : Dictionary = new Dictionary();
		public var editedElements : Dictionary = new Dictionary();
		
		public function FlairComponent(component : Object = null)
		{
			this.component = component;
			if (component is UIComponent) {
				var theComponent : IFlairComponent = this;
				UIComponent(component).addEventListener(MouseEvent.CLICK, function(event : MouseEvent) : void {
					FlairModelLocator.instance.currentComponent = theComponent;
					event.stopPropagation();
				});
			} 
		}
		
		public function duplicate () : IFlairComponent {
			var clasz : Class = getDefinitionByName(getQualifiedClassName(component)) as Class;
			var thisClasz : Class = getDefinitionByName(getQualifiedClassName(this)) as Class;
			var object : Object = new clasz();
			var duplicate : FlairComponent = new thisClasz(object);
			duplicateProperties(duplicate);
			return duplicate;
		}
		
		protected function duplicateProperties (duplicate : IFlairComponent) : void {
			for (var property : String in editedProperties) {
				duplicate.putValue(property, editedProperties[property]);
			}
			for (var style : String in editedStyles) {
				duplicate.putValue(style, editedStyles[style]);
			}
			for each (var subComponent : IFlairComponent in components) {
				duplicate.add(subComponent.duplicate());
			}
		}
		
		public function removeFromParent() : IFlairComponent {
			if (parentComponent != null) {
				var next : IFlairComponent = parentComponent.remove(IFlairComponent(this));
				return next;
			} else {
				return this;
			}
		}
		
		public final function remove(child : IFlairComponent) : IFlairComponent {
			var index : int = components.getItemIndex(child);
			if ( index == -1 ) {
				return this;
			}
			if (child.component is DisplayObject) {
				var uiComponent : DisplayObject = child.component as DisplayObject;
				component.removeChild(uiComponent);
			}
			components.removeItemAt(index);
			if (index < components.length) {
				return components.getItemAt(index) as IFlairComponent;
			} else if (components.length > 0) {
				return components.getItemAt(components.length - 1) as IFlairComponent;
			} else {
				return this;
			}
		} 
		
		public final function add(child:IFlairComponent, index : int = -1) : void
		{
			if (index == -1 || index > components.length) {
				index = components.length;
			}
			child.parentComponent = this;
			if (child.component is UIComponent) {
				var uiComponent : UIComponent = child.component as UIComponent;
				if (components.length == 0 && component is Container) {
					Container(component).removeAllChildren();
				}
				UIComponent(component).addChildAt(uiComponent, index);
				if (uiComponent is Container) {
					uiComponent.percentHeight = 100;
					uiComponent.percentWidth = 100;
					child.editedProperties["width"] = "100%";
					child.editedProperties["height"] = "100%"; 
				} 
				if (uiComponent is Box) {
					//child.putValue("verticalScrollPolicy", "off");
					//child.putValue("horizontalScrollPolicy", "off");
				}
				var textProperty : String = "";
				var textValue : String = "";
				if (uiComponent.hasOwnProperty("title")) {
					textProperty = "title";
					textValue = "Title";
				} else if (uiComponent.hasOwnProperty("text")) {
					textProperty = "text";
					textValue = "Text";
				} else if (uiComponent.hasOwnProperty("label")) {
					textProperty = "label";
					textValue = "Label";
				}  
				if (textProperty && (child.getValue(textProperty) == null) && (uiComponent is Panel || !(uiComponent is Container))) {
					child.putValue(textProperty, textValue);
				}
			} else {
				child.addToParent(index);
			}
			components.addItemAt(child, index);
		}
		
		public function addToParent(index : int = -1) : void {}
		
		public function get componentName() : String 
		{
			
			if (!parentComponent) {
				return "Application";
			}
			
			var componentName : String = getQualifiedClassName(component);
			componentName = componentName.substring(componentName.indexOf("::") + 2);
			
			if (componentId) {
				componentName += " " + componentId;
			} 
			if (component.hasOwnProperty('label') && component.label.length > 0 ) {
				componentName += " (" + component.label + ")";
			}
			return componentName;
		}
		
		public function swapChildren(first : Number, second : Number) : void
		{
			
		}
		
		public final function select() : void
		{
			//
		}
		
		public function putValue(property : String, value : Object) : Object
		{
			if (property=="componentId") {
				this.componentId = String(value);
				this.editedProperties["id"] = value;
				this.editedProperties[property] = value;
				return value;
			} else if (component.hasOwnProperty(property)) {
				if (value is String && String(value).indexOf("%") > 0) {
					putSize(property, String(value));
				} else {
					component[property] = value;
					this.editedProperties[property] = value;
				}
			} else if (component is UIComponent) {
				UIComponent(component).setStyle(property, value);
				this.editedStyles[property] = value;
			} else if (component is CSSStyleDeclaration) {
				CSSStyleDeclaration(component).setStyle(property, value);
				this.editedStyles[property] = value;
			}
			return value;
		}
		
		
		private function putSize(property : String, text : String) : void {
			if (text.length > 0 && text.charAt(text.length - 1) == '%') {
				var percentValue : Number = Number( text.substring(0, text.length - 1) );
				if (percentValue < 0) {
					return;
				}
				if (property == "width") {
					UIComponent(component).percentWidth = percentValue;
				} else {
					UIComponent(component).percentHeight = percentValue;
				}
			} else if (Number(text) >= 0) {
				if (property == "width") {
					UIComponent(component).width = Number(text);
				} else {
					UIComponent(component).height = Number(text);
				}
			}
			editedProperties[property] = text;
		}
		
		public function putValues(properties : Array, values : Array) : void
		{
			if (properties && properties.length == values.length) {
				for each(var prop : String in properties) {
					var value : Object = values[ArrayUtil.getItemIndex(prop, properties)];
					if (component.hasOwnProperty(prop)) {
						component[prop] = value;
						editedProperties[prop] = value;
					} else {
						component.setStyle(prop, value);
						editedStyles[prop] = value;
					}
				}
			}
		}
		
		public function getValue(property : String) : Object
		{
			if (component.hasOwnProperty(property)) {
				var value : Object = component[property];
				return value;
			} else if (component is UIComponent) {
				return component.getStyle(property);
			}  else if (component is CSSStyleDeclaration) {
				return CSSStyleDeclaration(component).getStyle(property);
			} else {
				return null;
			}
		}
		
		public function getArrayValue(forProp : Object, index : Number) : Object
		{
			if (forProp is Array) {
				var properties : Array = forProp as Array;
				if (component.hasOwnProperty(properties[index])) {
					return this[properties[index]];
				} else if (component is UIComponent) {
					return UIComponent(component).getStyle(properties[index]);
				} else if (component is CSSStyleDeclaration) {
					return CSSStyleDeclaration(component).getStyle(properties[index]);
				}
			} else if (forProp is String) {
				var property : String = forProp as String;
				var array : Array = [];
				if (component.hasOwnProperty(property)) {
					array = component[property] as Array;
				} else if (component is UIComponent) {
					array = UIComponent(component).getStyle(property) as Array;
				} else if (component is CSSStyleDeclaration) {
					array = CSSStyleDeclaration(component).getStyle(property) as Array;
				}
				if (index < array.length) {
					return array[index];
				} 
			}
			return null;
		}
		
	}
}